package com.fc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fc.dao.ProductMapper;
import com.fc.entity.Category;
import com.fc.entity.Product;
import com.fc.entity.ProductCategoryRelation;
import com.fc.entity.ProductDetailImages;
import com.fc.entity.input.DeleteBatchInput;
import com.fc.entity.input.ProductInput;
import com.fc.entity.input.ProductQueryInput;
import com.fc.entity.output.ProductOutput;
import com.fc.entity.query.PageQuery;
import com.fc.enums.DelFlagEnum;
import com.fc.enums.ImageEnum;
import com.fc.exception.BusinessException;
import com.fc.service.CategoryService;
import com.fc.service.ProductCategoryRelationService;
import com.fc.service.ProductDetailImagesService;
import com.fc.service.ProductService;
import com.fc.service.baseService.impl.BaseServiceImpl;
import com.fc.utils.ParseWrapper;
import com.fc.utils.ResultVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 产品表 服务实现类
 * </p>
 *
 * @author
 * @since 2024-11-05
 */
@Service
@RequiredArgsConstructor
public class ProductServiceImpl extends BaseServiceImpl<ProductMapper, Product> implements ProductService {

    private final ProductDetailImagesService detailImagesService;

    private final ProductCategoryRelationService proCatRelService;

    private final CategoryService categoryService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean add(ProductInput input) {
        input.setId(null);
        Product product = BeanUtil.copyProperties(input, Product.class);
        savePre(product);
        if (product.getId() == null) {
            throw new BusinessException(9999, "产品新增失败");
        }
        List<ProductCategoryRelation> proCatRelList = input.getTypes().stream().map(c -> {
            ProductCategoryRelation relation = new ProductCategoryRelation();
            relation.setProductId(product.getId());
            relation.setCategoryId(c);
            return relation;
        }).toList();
        proCatRelService.saveBatchPre(proCatRelList);
        List<ProductDetailImages> detailImageList = new ArrayList<>();
        List<ProductDetailImages> mainImages = input.getDetailImages().stream().filter(d -> d.getType().equals(ImageEnum.MAIN)).toList();
        //排除交集方法再看看
        List<ProductDetailImages> detailImages = input.getDetailImages().stream().filter(d -> d.getType().equals(ImageEnum.DETAIL)).toList();
        //利用集合底层数组的原理，给image设置index
        if (CollUtil.isNotEmpty(mainImages)) {
            for (int i = 0; i < mainImages.size(); i++) {
                mainImages.get(i).setImageIndex(i);
                mainImages.get(i).setProductId(product.getId());
            }
            detailImagesService.saveBatchPre(mainImages);
        }
        if (CollUtil.isNotEmpty(detailImages)) {
            for (int i = 0; i < detailImages.size(); i++) {
                detailImages.get(i).setImageIndex(i);
                detailImages.get(i).setProductId(product.getId());
            }
            detailImagesService.saveBatchPre(detailImages);
        }
        return true;
    }

    @Override
    public IPage<Product> getPage(PageQuery query, ProductQueryInput input) {
        QueryWrapper<Product> wrapper = ParseWrapper.parseWrap(input, Product.class);
        wrapper.lambda().eq(Product::getDelFlag, DelFlagEnum.NORMAL);
        if (CollUtil.isNotEmpty(input.getTypes())) {
            //分开查询，一个查询是并集
            List<ProductCategoryRelation> categoryRelationList = proCatRelService.list(new LambdaQueryWrapper<ProductCategoryRelation>()
                    //todo 感觉怪怪的
                    .eq(ProductCategoryRelation::getCategoryId, input.getTypes().get(0))
                    .eq(input.getTypes().get(1) != null, ProductCategoryRelation::getCategoryId, input.getTypes().get(1)));
            if (CollUtil.isNotEmpty(categoryRelationList)) {
                List<Long> productIds = categoryRelationList.stream().map(ProductCategoryRelation::getProductId).toList();
                wrapper.lambda().in(Product::getId, productIds);
            }
        }
        return page(Page.of(query.getPageNumber(), query.getPageSize()), wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean renew(ProductInput input) {
        Product product = getById(input.getId());
        if (product == null || product.getDelFlag().equals(DelFlagEnum.DELETED)) {
            throw new BusinessException(9999, "产品不存在");
        }
        updateByIdPre(BeanUtil.copyProperties(input, Product.class));
        proCatRelService.remove(new LambdaQueryWrapper<ProductCategoryRelation>()
                .eq(ProductCategoryRelation::getProductId, input.getId())
                .eq(ProductCategoryRelation::getDelFlag, DelFlagEnum.NORMAL));
        //todo 添加同时删除oss上图片代码
        detailImagesService.remove(new LambdaQueryWrapper<ProductDetailImages>()
                .eq(ProductDetailImages::getProductId, input.getId())
                .eq(ProductDetailImages::getDelFlag, DelFlagEnum.NORMAL));
        List<ProductCategoryRelation> proCatRelList = input.getTypes().stream().map(c -> {
            ProductCategoryRelation relation = new ProductCategoryRelation();
            relation.setProductId(input.getId());
            relation.setCategoryId(c);
            return relation;
        }).toList();
        proCatRelService.saveBatchPre(proCatRelList);
        List<ProductDetailImages> detailImageList = new ArrayList<>();
        List<ProductDetailImages> mainImages = input.getDetailImages().stream().filter(d -> d.getType().equals(ImageEnum.MAIN)).toList();
        //排除交集方法再看看
        List<ProductDetailImages> detailImages = input.getDetailImages().stream().filter(d -> d.getType().equals(ImageEnum.DETAIL)).toList();
        //利用集合底层数组的原理，给image设置index
        if (CollUtil.isNotEmpty(mainImages)) {
            for (int i = 0; i < mainImages.size(); i++) {
                mainImages.get(i).setImageIndex(i);
                mainImages.get(i).setProductId(input.getId());
            }
            detailImagesService.saveBatchPre(mainImages);
        }
        if (CollUtil.isNotEmpty(detailImages)) {
            for (int i = 0; i < detailImages.size(); i++) {
                detailImages.get(i).setImageIndex(i);
                detailImages.get(i).setProductId(input.getId());
            }
            detailImagesService.saveBatchPre(detailImages);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean del(DeleteBatchInput input) {
        List<Product> products = input.getIds().stream().map(i -> {
            Product product = new Product();
            product.setDelFlag(DelFlagEnum.DELETED);
            product.setId(i);
            return product;
        }).toList();
        updateBatchByIdPre(products);
        proCatRelService.remove(new LambdaQueryWrapper<ProductCategoryRelation>()
                .in(ProductCategoryRelation::getProductId, input.getIds())
                .eq(ProductCategoryRelation::getDelFlag, DelFlagEnum.NORMAL));
        //todo 添加同时删除oss上图片代码
        detailImagesService.remove(new LambdaQueryWrapper<ProductDetailImages>()
                .in(ProductDetailImages::getProductId, input.getIds())
                .eq(ProductDetailImages::getDelFlag, DelFlagEnum.NORMAL));
        return true;
    }

    @Override
    public ResultVO<ProductOutput> detail(Long id) {
        Product byId = getById(id);
        if (BeanUtil.isEmpty(byId) || byId.getDelFlag().equals(DelFlagEnum.DELETED)) {
            throw new BusinessException(9999, "产品不存在");
        }
        Map<Long, List<Category>> categoryMap = getCategories(Collections.singletonList(id));
        List<ProductDetailImages> detailImagesList = detailImagesService.list(new LambdaQueryWrapper<ProductDetailImages>()
                .eq(ProductDetailImages::getDelFlag, DelFlagEnum.NORMAL)
                .eq(ProductDetailImages::getProductId, id));
        List<ProductDetailImages> mainImages = detailImagesList.stream().filter(i -> i.getType().equals(ImageEnum.MAIN)).toList();
        List<ProductDetailImages> detailImages = detailImagesList.stream().filter(i -> i.getType().equals(ImageEnum.DETAIL)).toList();
        ProductOutput output = BeanUtil.copyProperties(byId, ProductOutput.class);
        output.setCategories(categoryMap.get(id));
        output.setDetailImages(detailImages);
        output.setMainImages(mainImages);
        return ResultVO.success(output);
    }

    @Override
    public Map<Long, List<Category>> getCategories(List<Long> proIds) {
        List<ProductCategoryRelation> relations = proCatRelService.list(new LambdaQueryWrapper<ProductCategoryRelation>()
                .eq(ProductCategoryRelation::getDelFlag, DelFlagEnum.NORMAL)
                .in(ProductCategoryRelation::getProductId, proIds));
        List<Long> categoryIds = relations.stream().map(ProductCategoryRelation::getCategoryId).toList();
        Map<Long, Category> categoryMap = categoryService.listByIds(categoryIds)
                .stream().collect(Collectors.toMap(Category::getId, o -> o));
        return relations.stream().collect(Collectors.groupingBy(
                ProductCategoryRelation::getProductId,
                Collectors.mapping(relation -> categoryMap.get(relation.getCategoryId()), Collectors.toList())
        ));
    }
}